<?php

import('work.libraries.access');

class acl extends Work
{
    /**
	 * 生成权限设置列表，并计算组的访问资源的权限
	 *
	 * @return  void
	 */
    public static function generate($component = 'root', $assetId = 1)
    {
        //Get the rules for just this asset (non-recursive)
        $assetRules = access::getAssetRules($assetId);
        $groups = self::getList();


        //$a = access::getAuthorisedViewLevels(11);

        //$inheritedRule = access::checkGroup(4, 'core.login.admin', $assetId);
        //echo $assetId;
        //$assetRule		 =  access::check(11,'menu.acl.group_index', $assetId);
        //var_dump($assetRule);
        //var_dump(access::check(43, 'core.delete'));

        //查找群组子节点的所有用户编号
        //$a = self::getUsersByGroup(2, true);

        //$a = access::getAuthorisedViewLevels(43);
        //print_r($a);
        
        $menus = Component::$menu;
        $access = Component::$access;

        //分析菜单，得到子菜单
        if(isset($menus[$component]) && is_array($menus[$component]))
        {
            $menu = array();
            foreach($menus[$component] as $_menus)
            {
                foreach($_menus as $_group)
                {
                    if(is_array($_group))
                    {
                        foreach($_group as $k => $child)
                        {
                            $_name = str_replace('/','.',$child['url']);
                            $_key = $child['type'].'.'.$_name;
                            $child['name'] = $_key;
                            $menu[$_key] = $child;
                        }
                    }
                }
            }
        }

        //菜单权限
        $actions = $menu;
        //功能权限

        if(isset($access[$component]) && is_array($access[$component]))
        {
            $actions += $access[$component];
        }

        $html = array();

        $curLevel = 0;

        //Start a row for each user group.
        foreach ($groups as $group)
        {
            $group = (object)$group;
            $difLevel = $group->level - $curLevel;

            if ($difLevel > 0) {
                $html[] = '<td><tr>';
            }
            elseif ($difLevel < 0) {
                $html[] = str_repeat('</tr></td>', -$difLevel);
            }

            $html[] = '<td>';

            $html[] = '<div class="panel">';
            $html[] =	'<h3 class="pane-toggler title"><a href="javascript:void(0);"><span>';
            $html[] =	str_repeat('<span id="level">|&ndash;</span> ', $curLevel = $group->level) . $group->description . ' ['.$group->title.']';
            $html[] =	'</span></a></h3>';
            $html[] =	'<div class="pane-slider content pane-hide">';
            $html[] =		'<div class="mypanel">';
            $html[] =			'<table class="group-rules" width="100%">';
            $html[] =				'<thead>';
            $html[] =					'<tr>';

            $html[] =						'<th align="left" class="actions" id="actions-th' . $group->id . '">';
            $html[] =							'<span class="acl-action">动作</span>';
            $html[] =						'</th>';

            $html[] =						'<th width="140" align="left" class="settings" id="settings-th' . $group->id . '">';
            $html[] =							'<span class="acl-action">选择规则<sup>[1]</sup></span>';
            $html[] =						'</th>';

            //The calculated setting is not shown for the root group of global configuration.
            $canCalculateSettings = ($group->parent_id || $component != 'root');
            if ($canCalculateSettings) {
                $html[] =					'<th width="160" align="left" id="aclactionth' . $group->id . '">';
                $html[] =						'<span class="acl-action">计算结果<sup>[2]</sup></span>';
                $html[] =					'</th>';
            }

            $html[] =					'</tr>';
            $html[] =				'</thead>';
            $html[] =				'<tbody>';

            foreach ($actions as $action)
            {
                $action = (object)$action;
                $html[] =				'<tr>';
                $html[] =					'<td headers="actions-th' . $group->id . '">';
                $html[] =						'<label class="hasTip" for="' .$component. '_' . $action->name . '_' . $group->id . '" title="'.$action->description.'">';
                $html[] =						 $action->title.' ['.$action->name.']';
                $html[] =						'</label>';
                $html[] =					'</td>';

                $html[] =					'<td headers="settings-th' . $group->id . '">';

                $html[] = '<select name="' .$component. '[' .$action->name . '][' . $group->id . ']" id="' .$component. '_' . $action->name . '_' . $group->id . '" title="'.$action->description.'">';

                $inheritedRule	= access::checkGroup($group->id, $action->name, $assetId);

                //Get the actual setting for the action for this group.
                $assetRule		= $assetRules->allow($action->name, $group->id);

                //Build the dropdowns for the permissions sliders

                //The parent group has "Not Set", all children can rightly "Inherit" from that.
                $html[] = '<option value=""' . ($assetRule === null ? ' selected="selected"' : '') . '>'. (empty($group->parent_id) && $component == 'root' ? '未设置' : '继承') . '</option>';
                $html[] = '<option value="1"' . ($assetRule === true ? ' selected="selected"' : '') . '>允许</option>';
                $html[] = '<option value="0"' . ($assetRule === false ? ' selected="selected"' : '') . '>禁止</option>';
                $html[] = '</select>';

                //If this asset's rule is allowed, but the inherited rule is deny, we have a conflict.
                if (($assetRule === true) && ($inheritedRule === false)) 
                {
                    $html[] = '冲突 ';
                }
            
                $html[] = '</td>';

                //Build the Calculated Settings column.
                //The inherited settings column is not displayed for the root group in global configuration.
                if ($canCalculateSettings) {
                    $html[] = '<td headers="aclactionth' . $group->id . '">';

                    //This is where we show the current effective settings considering currrent group, path and cascade.
                    //Check whether this is a component or global. Change the text slightly.

                    if (access::checkGroup($group->id, 'core.admin') !== true)
                    {
                        if ($inheritedRule === null) {
                            $html[] = '<span class="icon-16-unset">不允许</span>';
                        }
                        elseif ($inheritedRule === true)
                        {
                            $html[] = '<span class="icon-16-allowed">允许</span>';
                        }
                        elseif ($inheritedRule === false) {
                            if ($assetRule === false) {
                                $html[] = '<span class="icon-16-denied">不允许</span>';
                            }
                            else {
                                $html[] = '<span class="icon-16-denied"><span class="icon-16-locked">不允许(已锁定)</span></span>';
                            }
                        }
                    }
                    elseif ($component != 'root')
                    {
                        $html[] = '<span class="icon-16-allowed"><span class="icon-16-locked">允许(超级管理员)</span></span>';
                    }
                    else {
                        //Special handling for  groups that have global admin because they can't  be denied.
                        //The admin rights can be changed.
                        if ($action->name === 'core.admin') {
                            $html[] = '<span class="icon-16-allowed">允许</span>';
                        }
                        elseif ($inheritedRule === false) {
                            //Other actions cannot be changed.
                            $html[] = '<span class="icon-16-denied"><span class="icon-16-locked">冲突</span></span>';
                        }
                        else {
                            $html[] = '<span class="icon-16-allowed"><span class="icon-16-locked">允许(超级管理员)</span></span>';
                        }
                    }
                    $html[] = '</td>';
                }
                $html[] = '</tr>';
            }

            $html[] = '</tbody>';
            $html[] = '</table></div>';
            $html[] = '</div></div>';

            $html[] = '</td>';
        }
        $html[] = str_repeat('</tr></td>', $curLevel);
        return $html;
   }

    /**
	 * 获取树形数据库数据，获取的数据已经排序并且计算深度
	 *
	 * @return array
	 */
	public static function getList($table = 'acl_groups')
	{
        $res = Work::instance('Model')->execute("
            SELECT a.*, COUNT(DISTINCT b.id) AS level 
            FROM `#__{$table}` AS a 
            LEFT JOIN `#__{$table}` AS b ON a.lft > b.lft AND a.rgt < b.rgt 
            GROUP BY a.id 
            ORDER BY a.lft ASC
        ");

        if(is_array($res)) 
        {
            foreach($res as $key => $value)
            {
                $res[$key]['htmlLayer'] = str_repeat('<span id="level">|&ndash; </span>', $value['level']);
            }
        }
		return $res;
	}

	public static function getUsersByGroup($groupId, $recursive = false)
	{
		$test = $recursive ? '>=' : '=';

		//First find the users contained in the group
        $sql = 'SELECT DISTINCT(user_id), g2.id ';
        $sql .= ' FROM #__acl_groups as g1 ';
        $sql .= ' INNER JOIN #__acl_groups AS g2 ON g2.lft'.$test.'g1.lft AND g1.rgt'.$test.'g2.rgt ';
        $sql .= ' INNER JOIN #__acl_user_group_map AS m ON g2.id = m.group_id ';
        $sql .= ' WHERE g1.id = '.(int) $groupId;
        $sql .= ' ORDER BY g1.lft ASC ';

        $result = Work::instance('Model')->execute($sql);

        if (is_array($result))
        {
            $r = array();
            foreach ($result as $v)
            {
                $r[$v['id']][] = $v['user_id'];
            }
        }
		return $r;
	}

    /**
	 * 重建树形结构左右值，用于管理更新树形结构表后排序
	 *
	 * @return void
	 */
    function rebuild($table, $parent_id = 0, $left = 0)
	{ 
		//左值 +1 是右值
		$right = $left + 1;

		//获得这个节点的所有子节点
		$res = Work::instance('Model')->execute("SELECT `id` FROM `#__{$table}` WHERE `parent_id` = '".$parent_id."'");
        if(is_array($res)) 
        {
            foreach($res as $row)
            {
                //每个递归执行这个函数
                //这个节点的子
                //$right 是当前的右值，这是由 rebuildTree 函数递增
                $right = self::rebuild($table, $row['id'], $right);
            }
        }
		Work::instance('Model')->execute("UPDATE `#__{$table}` SET `lft` = '" . $left . "', `rgt` = '" . $right . "' WHERE `id` = '".$parent_id."' "); 
		//返回此节点的右值+1
		return $right + 1;
	} 

}